package com.xjrh.traintravel.collector.netty.handler;

import com.xjrh.middleware.redis.service.RedisService;
import com.xjrh.traintravel.collector.common.CodeConvertor;
import com.xjrh.traintravel.collector.common.ResultData;
import com.xjrh.traintravel.collector.common.StringUtil;
import com.xjrh.traintravel.collector.netty.coder.command.AgreementStructure;
import com.xjrh.traintravel.collector.pojo.config.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 参数读取指令处理类
 *
 * @author snps
 * @create 2022-01-27 11:55
 * @describe
 **/
@Component
@Slf4j
public class ConfigReadHandler extends BaseAgreementHandler {

    /**
     * 数据缓存时间（单位：分钟）
     */
    @Value("${project.dataCacheTime}")
    private long dataCacheTime;

    @Resource
    private RedisService redisService;


    /**
     * 发送读取配置命令
     * @param agreement 命令
     * @return ResultData
     */
    public ResultData sendReadCommand(AgreementStructure agreement) {
        /* 发送命令 */
        super.sendCommand(agreement);

        ResultData result = new ResultData(Boolean.TRUE);
        result.setResult(Boolean.TRUE);
        result.setInfo("发送指令成功！");
        result.setData(null);
        return result;
    }

    /**
     * 处理回复信息
     * @param agreement 命令
     */
    public void handleReplyData(AgreementStructure agreement) {
        String data = agreement.getData();
        if (StringUtil.isEmpty(data) || data.length() < 3) {
            log.error("接收到的 字符串数据 为空，不能转换为对应的命令！");
            return;
        }

        // 获取命令编号。根据命令编号做相应处理
        String commandNo = data.substring(0, 2);
        // 读取配置-主机信息 (01)
        if (commandNo.equals("01")) {
            InfoConfig config = readInfo(data);
            redisService.setCacheObject(agreement.getAddr() + "-config-" + config.getCommonNo(), config, dataCacheTime, TimeUnit.MINUTES);
            return;
        }
        // 读取配置-采集策略 (02)
        if (commandNo.equals("02")) {
            CollectionStrategyConfig config = readCollectionStrategy(data);
            redisService.setCacheObject(agreement.getAddr() + "-config-" + config.getCommonNo(), config, dataCacheTime, TimeUnit.MINUTES);
            return;
        }
        // 读取配置-故障分级 (03)
        if (commandNo.equals("03")) {
            FaultGradeConfig config =  readFaultGrade(data);
            redisService.setCacheObject(agreement.getAddr() + "-config-" + config.getCommonNo() + "-" + config.getType(),
                    config, dataCacheTime, TimeUnit.MINUTES);
            return;
        }
        // 读取配置-系统时间 (04)
        if (commandNo.equals("04")) {
            SystemTimeConfig config = readSystemTime(data);
            redisService.setCacheObject(agreement.getAddr() + "-config-" + config.getCommonNo(), config, dataCacheTime, TimeUnit.MINUTES);
            return;
        }
        // 读取配置-波磨设置 (05)
        if (commandNo.equals("05")) {
            CorrugationConfig config = readCorrugation(data);
            redisService.setCacheObject(agreement.getAddr() + "-config-" + config.getCommonNo(), config, dataCacheTime, TimeUnit.MINUTES);
            return;
        }
        // 读取配置-心跳设置 (06)
        if (commandNo.equals("06")) {
            HeartbeatConfig config = this.readHeartbeat(data);
            redisService.setCacheObject(agreement.getAddr() + "-config-" + config.getCommonNo(), config, dataCacheTime, TimeUnit.MINUTES);
            return;
        }
        // 读取配置-前置采集重置(0B)
        if (commandNo.equals("0A")) {
            Config0B config = this.readConfig0B(data);
            redisService.setCacheObject(agreement.getAddr() + "-config-" + config.getCommonNo(), config, dataCacheTime, TimeUnit.MINUTES);
            return;
        }
        // 读取配置-读取设备ID
        if (commandNo.equals("0B")) {
            Config0C config = this.readConfig0C(data);
            redisService.setCacheObject(agreement.getAddr() + "-config-" + config.getCommonNo(), config, dataCacheTime, TimeUnit.MINUTES);
            return;
        }

        log.error("接收到的命令编号：{} 错误，不能转换为对应的命令！");
        return;
    }

    /************************************************************
     * 读取配置-主机信息 (01)
     * @param data 字符串数据
     * @return InfoConfig
     */
    private InfoConfig readInfo(String data) {
        InfoConfig config = new InfoConfig();
        config.setCommonNo(data.substring(0, 2));
        config.setSettingType(Integer.parseInt(data.substring(2, 4), 16));
        config.setServerIp(CodeConvertor.hexString2Ip(data.substring(4, 12)));
        config.setServerPort(Integer.parseInt(data.substring(12, 16), 16));
        config.setEquipmentIp(CodeConvertor.hexString2Ip(data.substring(16, 24)));
        config.setEquipmentPort(Integer.parseInt(data.substring(24, 28), 16));
        config.setEquipmentMask(CodeConvertor.hexString2Ip(data.substring(28, 36)));
        config.setEquipmentGateway(CodeConvertor.hexString2Ip(data.substring(36, 44)));
        config.setEquipmentNumber(Integer.parseInt(data.substring(44, 46), 16));
        config.setTrainPart1No(data.substring(46, 52));
        config.setTrainPart2No(data.substring(52, 58));
        config.setTrainPart3No(data.substring(58, 64));
        config.setCarNo1Ip(CodeConvertor.hexString2Ip(data.substring(64, 72)));
        config.setCarNo6Ip(CodeConvertor.hexString2Ip(data.substring(72, 80)));
        config.setBackupServerIp(CodeConvertor.hexString2Ip(data.substring(80, 88)));
        config.setBackupEquipmentIp(CodeConvertor.hexString2Ip(data.substring(88, 96)));
        config.setBackupEquipmentGateway(CodeConvertor.hexString2Ip(data.substring(96)));
        return config;
    }

    /**
     * 读取配置-采集策略 (02)
     * @param data 字符串数据
     * @return CollectionStrategyConfig
     */
    private CollectionStrategyConfig readCollectionStrategy(String data) {
        CollectionStrategyConfig config = new CollectionStrategyConfig();
        config.setCommonNo(data.substring(0, 2));
        // 1-部件（轴向、电机、齿轮箱）
        config.setPartsStrategy(Integer.parseInt(data.substring(2, 4), 16));
        config.setPartsStrategySpeed(Integer.parseInt(data.substring(4, 6), 16));
        config.setPartsStrategyWave(Integer.parseInt(data.substring(6, 8), 16));
        config.setPartsStrategyTriggerTime(Integer.parseInt(data.substring(8, 10), 16));
        config.setPartsStrategyContinueTime(Integer.parseInt(data.substring(10, 12), 16));
        config.setPartsStrategyFrequencyUnit(Integer.parseInt(data.substring(12, 14), 16));
        config.setPartsStrategyFrequency(Integer.parseInt(data.substring(14, 16), 16));
        config.setPartsStrategyCollectionNumber(Integer.parseInt(data.substring(16, 18), 16));
        // 2-波磨
        config.setCorrugationStrategy(Integer.parseInt(data.substring(18, 20), 16));
        config.setCorrugationStrategySpeed(Integer.parseInt(data.substring(20, 22), 16));
        config.setCorrugationStrategyWave(Integer.parseInt(data.substring(22, 24), 16));
        config.setCorrugationStrategyTriggerTime(Integer.parseInt(data.substring(24, 26), 16));
        config.setCorrugationStrategyContinueTime(Integer.parseInt(data.substring(26, 28), 16));
        config.setCorrugationStrategyFrequencyUnit(Integer.parseInt(data.substring(28, 30), 16));
        config.setCorrugationStrategyFrequency(Integer.parseInt(data.substring(30, 32), 16));
        // 3-温度
        config.setTemperatureStrategy(Integer.parseInt(data.substring(32, 34), 16));
        config.setTemperatureStrategySpeed(Integer.parseInt(data.substring(34, 36), 16));
        config.setTemperatureStrategyWave(Integer.parseInt(data.substring(36, 38), 16));
        config.setTemperatureStrategyTriggerTime(Integer.parseInt(data.substring(38, 40), 16));
        config.setTemperatureStrategyContinueTime(Integer.parseInt(data.substring(40, 42), 16));
        config.setTemperatureStrategyFrequencyUnit(Integer.parseInt(data.substring(42, 44), 16));
        config.setTemperatureStrategyFrequency(Integer.parseInt(data.substring(44, 46), 16));
        return config;
    }

    /**
     * 读取配置-故障分级 (03)
     * @param data 字符串数据
     * @return FaultGradeConfig
     */
    private FaultGradeConfig readFaultGrade(String data) {
        int startIndex = 2, endIndex = 4;

        FaultGradeConfig config = new FaultGradeConfig();
        config.setCommonNo(data.substring(0, 2));
        config.setType(Integer.parseInt(data.substring(startIndex, endIndex), 16));
        startIndex = endIndex; endIndex = startIndex + 4;
        config.setLength(Integer.parseInt(data.substring(startIndex, endIndex), 16));
        startIndex = endIndex; endIndex = startIndex + config.getLength() * 2;
        config.setData(CodeConvertor.hexString2String(data.substring(startIndex, endIndex)));
        return config;
    }

    /**
     * 读取配置-系统时间 (04)
     * @param data 字符串数据
     * @return SystemTimeConfig
     */
    private SystemTimeConfig readSystemTime(String data) {
        SystemTimeConfig config = new SystemTimeConfig();
        config.setCommonNo(data.substring(0, 2));
        config.setYear(Integer.parseInt(data.substring(2, 4), 16));
        config.setMonth(Integer.parseInt(data.substring(4, 6), 16));
        config.setDay(Integer.parseInt(data.substring(6, 8), 16));
        config.setHour(Integer.parseInt(data.substring(8, 10), 16));
        config.setMinute(Integer.parseInt(data.substring(10, 12), 16));
        config.setSecond(Integer.parseInt(data.substring(12), 16));

        String datetime = new StringBuilder().append("20")
                .append(config.getYear()).append("-")
                .append(config.getMonth()>=10 ? config.getMonth() : "0"+config.getMonth()).append("-")
                .append(config.getDay()>=10 ? config.getDay() : "0"+config.getDay()).append(" ")
                .append(config.getHour()>=10 ? config.getHour() : "0"+config.getHour()).append(":")
                .append(config.getMinute()>=10 ? config.getMinute() : "0"+config.getMinute()).append(":")
                .append(config.getSecond()>=10 ? config.getSecond() : "0"+config.getSecond()).toString();
        config.setDatetime(datetime);
        return config;
    }

    /**
     * 读取配置-波磨设置 (05)
     * @param data 字符串数据
     * @return CorrugationConfig
     */
    private CorrugationConfig readCorrugation(String data) {
        CorrugationConfig config = new CorrugationConfig();
        config.setCommonNo(data.substring(0, 2));
        config.setCom1Model1(Integer.parseInt(data.substring(2, 4), 16));
        config.setCom1Model2(Integer.parseInt(data.substring(4, 6), 16));
        config.setCom2Model1(Integer.parseInt(data.substring(6, 8), 16));
        config.setCom2Model2(Integer.parseInt(data.substring(8), 16));
        return config;
    }

    /**
     * 读取配置-心跳设置 (06)
     * @param data 字符串数据
     * @return HeartbeatConfig
     */
    private HeartbeatConfig readHeartbeat(String data) {
        HeartbeatConfig config = new HeartbeatConfig();
        config.setCommonNo(data.substring(0, 2));
        config.setIntervalTime(Integer.parseInt(data.substring(2, 4), 16));
        config.setBreakCount(Integer.parseInt(data.substring(4), 16));
        return config;
    }

    /**
     * 读取配置-上传文件类型控制
     * @param data
     * @return
     */
    private Config0B readConfig0B(String data) {
        Config0B config = new Config0B();
        int[] arysBitValue = CodeConvertor.hexString2Bin(data, 8);
        config.setBit0(arysBitValue[0]);
        config.setBit1(arysBitValue[1]);
        return config;
    }

    /**
     * 读取配置-设备ID
     * @param data
     * @return
     */
    private Config0C readConfig0C(String data) {
        Config0C config = new Config0C();
        config.setData(data);
        return config;
    }


}